<template>
  <el-container
    v-if="templateOptions.length > 0 || !isComponent"
    v-loading="loading"
    :class="{ 'is-perview': isPreview }"
    class="wk-print-container">
    <el-header>
      <template v-if="isPreview">
        <el-button type="primary" @click="handleClick('download')">{{ `${perviewTypeName} 下载` }}</el-button>
        <el-button type="primary" @click="handleClick('print')">打印</el-button>
        <el-button @click="handleClick('goback')">取消</el-button>
      </template>
      <template v-else>
        <slot
          name="header"
          :print-templates="templateOptions" />
        <template v-if="!$slots.header">
          <span class="select-label">模板</span>
          <el-select
            v-model="templateId"
            style="width: 170px;"
            class="handle-item-content"
            @change="templateChange">
            <el-option
              v-for="item in templateOptions"
              :key="item.templateId"
              :label="item.templateName"
              :value="item.templateId" />
          </el-select>
          <template v-if="queryParams.showTyeSelect === undefined || queryParams.showTyeSelect">
            <span class="select-label">类型</span>
            <el-select
              v-model="perviewType"
              style="width: 80px;"
              class="handle-item-content">
              <el-option
                v-for="item in previewOptions"
                :key="item"
                :label="item"
                :value="item" />
            </el-select>
          </template>

          <el-tooltip
            v-if="perviewType === 'word'"
            effect="dark"
            content="word模板格式暂不支持水印功能"
            placement="bottom">
            <i class="wk wk-icon-fill-help wk-help-tips" />
          </el-tooltip>
          <div v-if="$slots['preview-button']" class="preview-button"><slot name="preview-button" /></div>
          <el-button v-else class="preview-button" type="primary" @click="printPreviewClick">打印预览</el-button>
        </template>
      </template>
    </el-header>
    <el-main>
      <div class="main-container">
        <div v-show="isPreview" class="main-content-default" :class="{'main-content': !isComponent}">
          <iframe
            id="wkPrint"
            :height="iframeHeight"
            :src="iframeUrl"
            style="width: 100%;height: calc(100% - 100px);margin-top: 54px;"
            scrolling="no"
            frameborder="0" />
        </div>
        <div v-show="!isPreview && queryParams.showTips" class="main-tips">您可以在当前页面对模板文字进行调整，确认无误后可进行打印</div>
        <div v-show="!isPreview" class="main-content-default" :class="{'main-content': !isComponent}">
          <tinymce
            ref="editor"
            v-model="content"
            :toolbar="toolbar"
            :plugins="plugins"
            :height="richHeight"
            :init="tinymceInit"
            :is-print="!isComponent"
            :class="{'log-print-tinymce': isComponent}"
            @onClick="tinyClick" />
        </div>
      </div>
    </el-main>

    <!-- CRM详情 -->
    <c-r-m-full-screen-detail
      :id="detailId"
      :visible.sync="detailShow"
      :crm-type="detailType" />
  </el-container>
</template>

<script>
import {
  oaLogPrintTemplatePreviewAPI,
  oaLogPrintTemplatePrintAPI,
  oaLogPrintTemplateQueryByIdAPI,
  oaLogPrintTemplateListAPI,
  oaLogPrintTemplateFieldsAPI
} from '@/api/admin/oa'
import { crmFileDownByPathAPI, downloadFileAPI } from '@/api/common'

import Tinymce from '@/components/Tinymce'
import Toolbar from '@/components/Tinymce/toolbar'
import Plugins from '@/components/Tinymce/plugins'

import { downloadFileWithBuffer } from '@/utils'
import { isArray, isObject } from '@/utils/types'
import { mapGetters } from 'vuex'
import { getFormFieldShowName } from '@/components/NewCom/WkForm/utils'

export default {
  name: 'Print',
  components: {
    Tinymce,
    CRMFullScreenDetail: () =>
      import('@/components/CRMFullScreenDetail')
  },
  beforeRouteUpdate(to, from, next) {
    this.content = ''
    next()
  },
  props: {
    /**
     * type history
     * id 日志模块id
     * templateId 模板id
     * dataType 'fields'  data: []  字段
     * showTyeSelect true
     * showTips: true
     */
    defaultQuery: Object, // 默认读取query 如果props 有值读取props
    data: [Array, Object], // 数据源
    editData: Object // 包含之前的内容 和 打印模板id
  },
  data() {
    return {
      loading: false,
      editorDom: null, // 编辑器的 $
      isPreview: false, // 是编辑 还是打印预览
      templateOptions: [],
      fieldObj: null, // 根据字段名对应字段对象
      templateId: '',
      typeId: '', // 模块对应的id
      previewOptions: ['pdf', 'word'],
      perviewType: 'pdf',
      content: '',
      historyData: null,
      showAtInfo: null, // at line 状态信息
      fieldHeaderObj: {}, // 包含打印导入的字段

      // 预览
      iframeUrl: '',
      iframeHeight: document.documentElement.clientHeight - 170,
      srcData: null,
      toolbar: `quick-button | ${Toolbar} | watermark | signature signature-top signature-bottom signature-left signature-right`,

      // 插件拼入
      detailId: '',
      detailShow: false,
      detailType: ''
    }
  },
  computed: {
    // 是按照组件 还是 按照路由页面
    isComponent() {
      return !!this.defaultQuery
    },
    ...mapGetters(['userDeptMap']),
    perviewTypeName() {
      return {
        word: 'Word',
        pdf: 'PDF'
      }[this.perviewType]
    },
    queryParams() {
      const defaultValue = {
        type: '', // history
        id: '', // 日志模块id
        templateId: '', // 模板id
        dataType: '', // fields
        showTyeSelect: true,
        showTips: true,
        tinymceInit: {}, // 富文本配置
        tinyAutoresize: true // 默认自动计算高度
      }

      const enterValue = this.defaultQuery || this.$route.query || {}
      return { ...defaultValue, ...enterValue }
    },

    // 富文本高度
    richHeight() {
      // (document.documentElement.clientHeight - 310)
      return this.isComponent ? (document.documentElement.clientHeight - 330) : (document.documentElement.clientHeight - 152)
    },
    // 富文本插件 包含自动高度
    plugins() {
      return this.isComponent ? `${Plugins} watermark  signature` : `${Plugins} watermark signature`
    },

    // 富文本配置
    tinymceInit() {
      const self = this
      return {
        statusbar: false,
        extended_valid_elements: 'span[class|title|wktag|style|contenteditable]',
        content_style: `p { margin: 5px 0;}
              .wk-at-tag {
                color: #005af3;
              }
              `,
        content_css: ['./static/tinymce/css/tiny-wk-word.css'],
        setup: function(editor) {
          // 如果是组件展示，加入前端修改输入内容的逻辑
          if (self.isComponent) {
            editor.on('setcontent', function(e) {
              if (!self.editorDom && e.content && e.target && e.target['$']) {
                // 编辑场景
                // if (self.editData) {
                //   self.editorDom = e.target
                // } else {
                self.refreshFieldsContent(e.target)
                // }
              }
            })
          }
        },
        ...this.queryParams.tinymceInit
      }
    }
  },
  created() {
    // 去除打印
    this.toolbar = this.toolbar.replace('print ', '')

    if (this.queryParams.type == 'history') {
      // this.getRecordDetail()
    } else {
      this.typeId = this.queryParams.id
      this.getTemplateOptions(this.queryParams.templateId)
    }

    window.addEventListener('resize', this.changeIframeHeight)
  },

  beforeDestroy() {
    window.removeEventListener('resize', this.changeIframeHeight)
  },
  methods: {
    changeIframeHeight() {
      this.iframeHeight = document.documentElement.clientHeight - 170
    },

    /**
     * 获取模板配置
     */
    getTemplateOptions(templateId) {
      this.loading = true
      oaLogPrintTemplateListAPI({
        configId: templateId,
        pageType: 0,
        type: 2 // 0查询管理员配置的，1查询个人的，2查询全部的
      })
        .then(res => {
          this.templateOptions = res.data.list || []
          this.$emit('pint-templates-change', this.templateOptions)

          if (this.queryParams.type != 'history') {
            if (this.templateOptions.length) {
              // 是编辑场景，复制保存的id
              if (this.editData && this.editData.printTemplateId) {
                this.templateId = this.editData.printTemplateId
              } else {
                this.templateId = this.templateOptions[0].templateId
              }

              this.templateChange()
            } else {
              this.templateId = ''
            }
          }

          this.loading = false
        })
        .catch(() => {
          this.loading = false
        })
    },

    /**
     * @description: 获取详情
     * @param {*} templateId 打印模板id
     * @param {*} refreshPreview 刷新预览字段
     * @return {*}
     */
    getTemplateDetail(templateId, refreshPreview) {
      this.loading = true
      const template = this.templateOptions.find(item => item.templateId === templateId)

      const requests = [oaLogPrintTemplateQueryByIdAPI({ templateId })]
      if (!this.fieldObj) {
        requests.push(oaLogPrintTemplateFieldsAPI({ logTemplateId: template?.configId }))// configId 日志模板id)
      }
      Promise.all(requests).then(resArr => {
        // this.editorDom 清空它，重新触发更新
        if (refreshPreview) {
          this.editorDom = null
        }

        if (resArr[0]) {
          // 编辑场景下直接展示编辑内容
          if (this.editData && this.editData.printTemplateId === templateId) {
            this.content = this.editData.printContent
          } else {
            const data = resArr[0].data || {}
            this.content = data.content
          }
        }

        if (resArr[1]) {
          const data = resArr[1].data || {}
          const fieldObj = {}
          data.forEach(item => {
            fieldObj[item.fieldName] = item
          })
          this.fieldObj = fieldObj
        }

        this.loading = false
      }).catch(() => {
        this.loading = false
      })
    },

    /**
     * @description: 刷新字段内容
     * @return {*}
     */
    refreshFieldsContent(editorDom) {
      this.editorDom = editorDom
      var { $ } = this.editorDom
      var children = Array.from($('span[data-wk-tag]'))
      children.forEach(item => {
        const wkTag = item.dataset.wkTag
        const fieldName = wkTag.split('.')[1]
        if (fieldName && this.data) {
          const field = this.fieldObj[fieldName]
          if (field.formType === 'rich_text_format') {
            item.innerHTML = this.getFieldShowValue(fieldName, this.data)
          } else {
            item.innerText = this.getFieldShowValue(fieldName, this.data)
          }
        }
      })

      var tableChildren = Array.from($('table[data-wk-table-tag="table"]'))
      tableChildren.forEach(table => {
        table.parentNode.removeChild(table)
      })

      this.content = this.$refs.editor.editor.getContent()
    },

    /**
     * @description: 刷新对应字段内容
     * @param {*} data
     * @return {*}
     */
    refreshContentByField(fieldName, data) {
      const fieldData = data || this.data
      if (!fieldData) return
      if (!this.editorDom) return
      var { $ } = this.editorDom
      var children = Array.from($('span[data-wk-tag]'))
      for (let index = 0; index < children.length; index++) {
        const item = children[index]
        if (fieldName && fieldData && item.dataset.wkTag.includes(fieldName)) {
          const field = this.fieldObj[fieldName]
          if (field.formType === 'rich_text_format') {
            item.innerHTML = this.getFieldShowValue(fieldName, fieldData)
          } else {
            item.innerText = this.getFieldShowValue(fieldName, fieldData)
          }
          break
        }
      }

      this.content = this.$refs.editor.editor.getContent()
    },

    /**
     * @description: 获取字段展示值
     * @return {*}
     */
    getFieldShowValue(fieldName, fieldData) {
      const field = this.fieldObj[fieldName]
      const dataValue = fieldData[fieldName] || ''
      if (field) {
        if (field.formType === 'location') {
          return isObject(dataValue) ? dataValue.address : ''
        } else if (['position', 'file'].includes(field.formType)) {
          return isArray(dataValue) ? dataValue.map(item => item.name).join(',') : ''
        } else if (field.formType === 'user') {
          return isArray(dataValue) ? dataValue.map(id => {
            const user = this.userDeptMap[`user-${id}`]
            return user?.realname || ''
          }).join(',') : ''
        } else if (field.formType === 'structure') {
          return isArray(dataValue) ? dataValue.map(id => {
            const user = this.userDeptMap[`dept-${id}`]
            return user?.name || ''
          }).join(',') : ''
        }
      }
      return dataValue
    },

    /**
     * @description: 模板调整
     * @return {*}
     */
    templateChange(templateId) {
      if (templateId && this.templateId !== templateId) {
        this.templateId = templateId
      }
      // 是前台处理，直接展示模板
      if (this.queryParams.dataType === 'fields') {
        // templateId 存在时，刷明切换了模板，需要重新重置字段
        this.getTemplateDetail(this.templateId, !!templateId)
      } else {
        this.getDetail()
      }
    },

    /**
     * 详情
     */
    getDetail() {
      this.loading = true
      oaLogPrintTemplatePrintAPI({
        templateId: this.templateId,
        id: this.typeId
      })
        .then(res => {
          this.loading = false
          const hasValues = !!this.content
          this.content = res.data
          if (hasValues) {
            this.$nextTick(() => {
              this.$refs.editor.updateIframeHeight()
            })
          }
        })
        .catch(() => {
          this.loading = false
        })
    },

    /**
     * 详情
     */
    // getRecordDetail() {
    //   this.loading = true
    //   printRecordDetailAPI({
    //     recordId: this.queryParams.recordId
    //   })
    //     .then(res => {
    //       this.loading = false
    //       const data = res.data || {}
    //       this.historyData = data
    //       this.templateId = data.templateId
    //       this.typeId = data.typeId

    //       this.getTemplateOptions(data.crmType)
    //       this.content = data.recordContent || ''
    //     })
    //     .catch(() => {
    //       this.loading = false
    //     })
    // },

    /**
       * 打印
       */
    compactPrint() {
      this.$refs.editor.editor.execCommand('mcePrint')
      // this.savePrintRecord()
    },

    /**
     * 打印预览
     */
    printPreviewClick() {
      this.loading = true
      oaLogPrintTemplatePreviewAPI({
        type: this.perviewType,
        content: this.content
      })
        .then(res => {
          this.loading = false
          const data = res.data
          const iframeUrl = `/oaLogPrintTemplate/preview.pdf?type=1&key=${data}`
          downloadFileAPI(iframeUrl).then(res => {
            this.iframeUrl = window.URL.createObjectURL(res.data)
          }).catch(() => {})

          this.srcData = data
          this.isPreview = true
        })
        .catch(() => {
          this.loading = false
        })
    },

    /**
     *保存打印记录
     */
    // savePrintRecord() {
    //   if (this.templateId && this.typeId) {
    //     printSaveRecordAPI({
    //       templateId: this.templateId,
    //       typeId: this.typeId,
    //       recordContent: this.content
    //     })
    //       .then(res => {
    //       })
    //       .catch(() => {
    //       })
    //   }
    // },

    hidenView() {
      this.$emit('close')
    },

    /**
     * @description: 预览页面逻辑
     * @param {*} type
     * @return {*}
     */
    handleClick(type) {
      if (type == 'goback') {
        this.isPreview = false
      } else if (type == 'print') {
        document.getElementById('wkPrint').contentWindow.print() // 调用浏览器的打印功能打印指定区域
        // this.savePrintRecord()
      } else if (type == 'download') {
        if (this.srcData) {
          var ext = this.perviewType
          const path = this.srcData
          var data = {
            key: path,
            type: ext === 'word' ? 2 : 1
          }
          ext = ext === 'word' ? 'doc' : 'pdf'
          crmFileDownByPathAPI(data).then(res => {
            downloadFileWithBuffer(res.data, `文档.${ext}`)
          }).catch(() => {})
        }
      }
    },

    /**
     * @description: 获取@后的关键词
     * @param {*} raw
     * @return {*}
     */
    replaceString(raw, type = 'at') {
      const regx = type === 'at' ? /@([^@\s]*)$/ : /\/([^\/\s]*)$/
      return raw.replace(regx, '')
    },

    /**
     * @description: 获取光标位置
     * @return {*}
     */
    getCursorIndex() {
      const selection = this.$refs.editor.editor.selection.getSel()
      return selection?.focusOffset
    },

    /**
     * @description: 获取节点
     * @return {*}
     */
    getRangeNode() {
      const selection = this.$refs.editor.editor.selection.getSel()
      return selection?.focusNode
    },

    /**
     * @description: 获取 @ 用户
     * @return {*}
     */
    getAtUser(type) {
      const content = this.getRangeNode()?.textContent || ''
      const regx = type === 'at' ? /@([^@\s]*)$/ : /\/([^\/\s]*)$/
      const match = regx.exec(content.slice(0, this.getCursorIndex()))
      if (match && match.length === 2) {
        return match[1]
      }
      return undefined
    },

    /**
     * @description: 获取位置
     * @return {*}
     */
    getRangeRect() {
      const selection = this.$refs.editor.editor.selection.getSel()
      const range = selection?.getRangeAt(0)
      const rect = range.getClientRects()[0]
      const LINE_HEIGHT = 65
      return {
        x: rect.x - 12,
        y: rect.y + LINE_HEIGHT
      }
    },

    /**
     * @description: 是否展示 @ 数据选择框
     * @return {*}
     */
    showAt() {
      const node = this.getRangeNode()
      if (!node || node.nodeType !== Node.TEXT_NODE) return false
      const content = node.textContent || ''
      const atRegx = /@([^@\s]*)$/
      const cursorIndex = this.getCursorIndex()
      const match = atRegx.exec(content.slice(0, cursorIndex))
      if (match && match.length === 2) {
        return {
          type: 'at',
          value: true
        }
      }

      const lineRegx = /\/([^\/\s]*)$/
      const lMatch = lineRegx.exec(content.slice(0, cursorIndex))
      return {
        type: 'line',
        value: lMatch && lMatch.length === 2
      }
    },

    /**
     * @description: 编辑器点击
     * @return {*}
     */
    tinyClick(event) {
      if (event.target) {
        const target = event.target
        const { dataset } = target
        if (dataset && dataset.wkType && dataset.wkTypeId) {
          this.detailId = dataset.wkTypeId
          this.detailType = dataset.wkType
          this.detailShow = true
        }
      }
    },

    /**
     * @description: 移除At输入的节点
     * @return {*}
     */
    getRemoveInputNode() {
      const node = this.getRangeNode()
      if (node) {
        const content = node?.textContent || ''
        const endIndex = this.getCursorIndex()
        const preSlice = this.replaceString(content.slice(0, endIndex), this.showAtInfo.type)
        const restSlice = content.slice(endIndex)

        const parentNode = node?.parentNode
        parentNode && parentNode.removeChild(node)

        return {
          preSlice,
          restSlice
        }
      }

      return {
        preSlice: '',
        restSlice: ''
      }
    },

    /**
     * 获取产品表
     */
    getTableList(type, list) {
      const fields = (this.fieldHeaderObj[type] || []).filter(item => {
        return !['handwriting_sign', 'field_tag', 'boolean_value'].includes(item.formType) && !['status'].includes(item.fieldName)
      }).slice(0, 8)

      let headerTD = ''
      fields.forEach(item => {
        headerTD += `<td data-wk-table-td-tag="name">${item.name}</td>`
      })

      let itemTD = ''
      list.forEach(data => {
        let temps = ''
        fields.forEach(item => {
          temps += `<td  data-wk-table-td-tag="value">
          <span data-wk-type="${type}" data-wk-type-id="${data[`${type}Id`]}">${this.fieldFormatter(data, item)}</span>
          </td>`
        })
        itemTD += `<tr data-wk-table-tr-tag="value">${temps}</tr>`
      })
      return `<table data-wk-table-tag="table" style="border-collapse: collapse; width: 100%;" border="1" >
      <tbody><tr data-wk-table-tr-tag="header">${headerTD}</tr>${itemTD}
      </tbody>
      </table>`
    },

    fieldFormatter(row, field) {
      if (field) {
        return getFormFieldShowName(field.formType, row[field.fieldName], '', field)
      }
      return row[field.fieldName] === '' || row[field.fieldName] === null ? '' : row[field.fieldName]
    },

    /**
     * span 颜色
     */
    getSpanColorClass(key) {
      const color = ['customer', 'contacts', 'business', 'contract', 'receivables', 'product'].includes(key) ? key : 'common'
      return `wk-tiny-tag--${color}`
    }
  }
}
</script>

<style lang="scss">
.log-print-tinymce {
  .tox .tox-edit-area__iframe {
    padding: 40px;
  }
}
</style>
<style lang="scss" scoped>
.wk-print-container {
  .el-header {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    height: 60px;
    padding: 0 70px;
    background-color: white;
    box-shadow: 0 1px 2px #dbdbdb;

    .wk-help-tips {
      margin-left: 8px;
    }

    .select-label {
      margin-right: 15px;
    }

    .el-select + .select-label {
      margin-left: 30px;
    }
  }

  .preview-button {
    position: absolute;
    top: 16px;
    right: 70px;
  }

  .el-main {
    padding: 0;
  }

  &.is-perview {
    .el-header {
      display: block;
      line-height: 60px;
      text-align: right;
    }
  }
}

.main-container {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;

  .main-tips {
    margin: 20px 0;
    font-size: 13px;
    color: #bfbfbf;
    text-align: center;
  }

  .main-content-default {
    flex: 1;
  }

  .main-content {
    width: 66%;
    margin: 0 auto;
  }
}

.module-type-select-wrap,
.module-select-wrap {
  position: absolute;
  z-index: 2;
}
</style>
